package com.mingqijia.gassafety.shared.utils.commonUtils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gap.basic.exception.BizException;
import com.mingqijia.gassafety.db.entity.Organization;
import com.mingqijia.gassafety.db.mapper.OrganizationMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 文件导出工具类
 *
 * @author wanghai
 * @since 2022-02-21
 */

@Slf4j
@Component
public class ExportUtils {

    private static final String SYSTEM = "gassafe-webserver";
    private static final String add = "/api/task/add";
    private static final String search = "/api/task/search";
    private static final Map<String, Object> headers = new HashMap<>();

    @Value("${data-exporter.service.url}")
    private String domain;
    /**
     * 导出任务创建
     *
     * @param params
     * @return
     */
    public Long createTask(JSONObject params) {
        Long taskId = null;
        String url = domain + add;
        log.info("createTask调用外部接口请求数据：url:{},入参:{}", url, JSONObject.toJSONString(params));
        try {
            String body = HttpRequest.post(url).body(JSONObject.toJSONString(params)).execute().body();
            log.info("调用外部接口返回数据：出参:{}", body);
            JSONObject res = JSONObject.parseObject(body);
            if (!res.get("code").equals(0)) {
                throw new BizException(res.get("msg") + "");
            }
            taskId = Long.parseLong(res.get("data") + "");
        } catch (Exception e) {
            log.error("ExportUtils.createTask创建任务失败:{}", e);
        }
        return taskId;
    }
    /**
     * 对字段进行校验,生成customized_table_header
     *
     * @param fieldMaps 需要单独设定format时，映射体（可为空）
     * @param fieldList 字段数组
     * @param titleList 字段对应title
     * @return
     */
    public static Map<String, Object> getCustomizedTableHeader(List<FieldMap> fieldMaps, String[] fieldList
            , String[] titleList) {
        List<String> fields = new ArrayList<>( Arrays.asList(fieldList));
        List<String> titles = new ArrayList<>(Arrays.asList(titleList));
        if (CollectionUtil.isEmpty(fields) || CollectionUtil.isEmpty(titles) || fields.size() != titles.size())
            throw new BizException("表头和字段不匹配");
        Map<String, Object> resultMap = new HashMap<>();
        if (CollectionUtil.isEmpty(fields)) return resultMap;
        for (int i = 0; i < fields.size(); i++) {
            String s = fields.get(i);
            if (s == null) log.error("getCustomizedTableHeader传入的filed有问题:{}", JSONObject.toJSONString(fields));
            List<FieldMap> collect = fieldMaps == null ? null : fieldMaps.stream().filter(fieldMap -> {
                return s.equals(fieldMap.field);
            }).collect( Collectors.toList());
            if (CollectionUtil.isEmpty(collect)) {
                resultMap.put(s, new CustomizedTableHeader(titles.get(i), i + 1));
            } else {
                resultMap.put(s, new CustomizedTableHeader(titles.get(i), collect.get(0).format, i + 1));
            }
        }
        log.info("getCustomizedTableHeader结果为:{}", JSONObject.toJSONString(resultMap));
        return resultMap;
    }

    public static Map<String, Object> getCustomizedTableHeaderWithOrganization(List<FieldMap> fieldMaps, String[] fieldList
            , String[] titleList) {
        List<String> fields = new ArrayList<>( Arrays.asList(fieldList));
        List<String> titles = new ArrayList<>(Arrays.asList(titleList));
        if (CollectionUtil.isEmpty(fields) || CollectionUtil.isEmpty(titles) || fields.size() != titles.size())
            throw new BizException("表头和字段不匹配");
        Map<String, Object> resultMap = new HashMap<>();
        if (CollectionUtil.isEmpty(fields)) return resultMap;
        //父级组织
        resultMap.put("spName", new CustomizedTableHeader("所属组织", 1));
        for (int i = 0; i < fields.size(); i++) {
            String s = fields.get(i);
            if (s == null) log.error("getCustomizedTableHeader传入的filed有问题:{}", JSONObject.toJSONString(fields));
            List<FieldMap> collect = fieldMaps == null ? null : fieldMaps.stream().filter(fieldMap -> {
                return s.equals(fieldMap.field);
            }).collect( Collectors.toList());
            if (CollectionUtil.isEmpty(collect)) {
                resultMap.put(s, new CustomizedTableHeader(titles.get(i), i + 2));
            } else {
                resultMap.put(s, new CustomizedTableHeader(titles.get(i), collect.get(0).format, i + 2));
            }
        }
        log.info("getCustomizedTableHeader结果为:{}", JSONObject.toJSONString(resultMap));
        return resultMap;
    }

    /**
     * 封装创建任务参数
     *
     * @param code                  必填 string 数据表种类代号
     * @param name                  选填 string 任务名称
     * @param creator               必填 string 任务创建者
     * @param queryUrl              必填 string 数据查询接口地址
     * @param headers               选填 object 数据查询接口需要的header
     * @param queryBody             选填 string 数据查询接口需要的body
     * @param customizedTableHeader 必填 map[string]object 导出数据表表头和数据查询接口返回数据关系
     * @param customizedSileName    选填 string 默认使用code的内容做文件名
     * @param mode                  必填 int 执行模式 1:立即执行,2定时执行
     * @param cronAt                mode=2时必填 int 任务指定执行时间(秒时间戳)
     * @param subscriberEmail       选填 list<string> 导出数据表后, 会将导出结果(成功或失败)发送到这些邮箱
     * @return
     */
    public static JSONObject getCreateTaskParams(String code, String name
            , String creator, String queryUrl, Map<String, Object> headers, String queryBody
            , Map<String, Object> customizedTableHeader, String customizedSileName, Integer mode, Integer cronAt,
                                                 List<String> subscriberEmail) {
        //必传字段校验
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(creator) || StringUtils.isEmpty(queryUrl)
                || mode == null || customizedTableHeader == null || (mode == 2 && cronAt == null))
            throw new BizException("必填字段为空");
        JSONObject params = new JSONObject();
        params.put("system", SYSTEM);
        params.put("code", code);
        params.put("creator", creator);
        params.put("query_url", queryUrl);
        params.put("customized_table_header", customizedTableHeader);
        if (!StringUtils.isEmpty(code)) params.put("name", name);
        if (!StringUtils.isEmpty(queryBody)) params.put("query_body", queryBody);
        if (!StringUtils.isEmpty(customizedSileName)) params.put("customized_file_name", customizedSileName);

        params.put("query_header", getHeader(headers));
        if (mode != null) params.put("mode", mode);
        if (mode == 2 && cronAt != null) params.put("cron_at", cronAt);
        if (!CollectionUtil.isEmpty(subscriberEmail)) params.put("subscriber_email", subscriberEmail);
        return params;
    }

    private static Map<String, Object> getHeader(Map<String, Object> additionalHeader) {
        headers.clear();
        headers.put("Content-Type", "application/json");
        if (additionalHeader != null && additionalHeader.keySet().size() > 0) {
            additionalHeader.forEach((s, o) -> {
                headers.put(s, o);
            });
        }
        return headers;
    }


    /**
     * 封装查询任务参数
     *
     * @param code              选填 string 数据表种类代号 精确匹配
     * @param name              选填 string 任务名称 模糊匹配
     * @param creator           选填 string 任务创建者 精确匹配
     * @param create_time_start 选填 int 创建时间开始(秒时间戳)
     * @param create_time_end   选填 int 创建时间结束(秒时间戳)
     * @param page              选填 int 默认 1
     * @param page_size         选填 int 默认 10
     * @return
     */
    public static JSONObject getSearchTaskParams(String code, String name, String creator,
                                                 Integer create_time_start, Integer create_time_end,
                                                 Integer page, Integer page_size) {
        JSONObject params = new JSONObject();
        JSONObject query = new JSONObject();
        query.put("system", SYSTEM);
        if (!StringUtils.isEmpty(code)) query.put("code", code);
        if (!StringUtils.isEmpty(name)) query.put("name", name);
        if (!StringUtils.isEmpty(creator)) query.put("creator", creator);
        if (!StringUtils.isEmpty(create_time_start)) query.put("create_time_start", create_time_start);
        if (!StringUtils.isEmpty(create_time_end)) query.put("create_time_end", create_time_end);
        params.put("query", query);
        if (page != null) params.put("query", query);
        if (page_size != null) params.put("page_size", page_size);
        return params;
    }

    /**
     * 导出任务查询
     *
     * @param params
     * @return
     */
    public JSONObject searchTask(JSONObject params) {
        String url = domain + search;
        log.info("searchTask调用外部接口请求数据：url:{},入参:{}", url, JSONObject.toJSONString(params));
        String body = "";
        JSONObject jsonObject = new JSONObject();
        try {
            body = HttpRequest.post(url).body(JSONObject.toJSONString(params)).execute().body();
            log.info("调用外部接口返回数据：出参:{}", body);
            JSONObject res = JSONObject.parseObject(body);
            if (!res.get("code").equals(0)) {
                throw new BizException(res.get("msg") + "");
            }
            jsonObject = res.getJSONObject("data");

            log.info(jsonObject.toString());
        } catch (Exception e) {
            log.error("ExportUtils.searchTask查询任务失败:{}", e);
            return jsonObject;
        }
        return jsonObject;
    }



}


@Data
class CustomizedTableHeader {
    String title;// 必填 string 在导出的数据表中表头
    int format = 0;// 选填 int , 默认0 为字符串
    int sort = 1;  //必填 int 在表头中的位置排序, 如有排序值一样的西段, 排序随机
    String field ;



    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CustomizedTableHeader that = (CustomizedTableHeader) o;
        return format == that.format &&
                sort == that.sort &&
                Objects.equals(title, that.title);
    }

    @Override
    public int hashCode() {

        return Objects.hash(title, format, sort);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getFormat() {
        return format;
    }

    public void setFormat(int format) {
        this.format = format;
    }

    public int getSort() {
        return sort;
    }

    public void setSort(int sort) {
        this.sort = sort;
    }

    public CustomizedTableHeader(String title, int format, int sort) {
        this.title = title;
        this.format = format;
        this.sort = sort;
    }

    public CustomizedTableHeader(String title, Integer sort) {
        this.title = title;
        this.sort = sort;
    }
}
class FieldMap {
    String field;
    int format = 0;// 选填 int , 默认0 为字符串, 具体选择参考下方的附录


    public FieldMap(String field, int format) {
        this.field = field;
        this.format = format;
    }
}